package it.unipd.fbaron.mind_reader_squared.activities;

import it.unipd.fbaron.mind_reader_squared.R;
import it.unipd.fbaron.mind_reader_squared.model.DataBaseHelper;
import it.unipd.fbaron.mind_reader_squared.model.ProfileDAO;
import it.unipd.fbaron.mind_reader_squared.model.ProfileLogic;

import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;

public class LoginActivity extends BaseActivity {

	// Login form UI elements
	LinearLayout loginLayout;
	Spinner userSpinner;
	EditText passwordEdit;
	Button registerNowButton;
	Button loginButton;

	// Register form UI elements
	LinearLayout registerLayout;
	EditText firstNameEdit;
	EditText lastNameEdit;
	EditText passwordRegistrationEdit;
	Spinner localeSpinner;
	DatePicker birthdayPicker;
	Button loginNowButton;
	Button registerButton;

	// Dialogs
	static final int DIALOG_FIELD_ERROR_ID = 1;
	static final int DIALOG_REGISTER_SUCCESS_ID = 2;
	static final int DIALOG_REGISTER_FAIL_ID = 3;
	static final int DIALOG_LOGIN_FAIL_ID = 4;

	// Arrays used to manage spinner objects
	ArrayAdapter<ProfileDAO> userAdapter;
	ArrayList<Locale> localeList;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.login_layout);

		// UI Variables initialization
		loginLayout = (LinearLayout) findViewById(R.id.login_layout);
		registerLayout = (LinearLayout) findViewById(R.id.register_layout);
		localeSpinner = (Spinner) findViewById(R.id.locale_spinner);
		registerNowButton = (Button) findViewById(R.id.register_now_button);
		loginNowButton = (Button) findViewById(R.id.login_now_button);
		loginButton = (Button) findViewById(R.id.login_button);
		registerButton = (Button) findViewById(R.id.register_button);
		firstNameEdit = (EditText) findViewById(R.id.first_name);
		lastNameEdit = (EditText) findViewById(R.id.last_name);
		passwordRegistrationEdit = (EditText) findViewById(R.id.password_register);
		birthdayPicker = (DatePicker) findViewById(R.id.birthdate_date_piker);
		userSpinner = (Spinner) findViewById(R.id.user_spinner);
		passwordEdit = (EditText) findViewById(R.id.password_edit);

		// LocaleSpinner population
		// Display all the available languages (declared in languages_data.xml)
		// with system default language in first position. lacolaList array is
		// used to keep memory of the ISO639 names.
		ArrayAdapter<String> localeStringAdapter = new ArrayAdapter<String>(
				this, android.R.layout.simple_spinner_item);
		localeList = new ArrayList<Locale>();
		Locale[] avaibleLocales = Locale.getAvailableLocales();
		String defaultLanguage = Locale.getDefault().getDisplayLanguage();
		String tmp = Locale.getDefault().getDisplayLanguage();
		localeStringAdapter.add(defaultLanguage);
		localeList.add(Locale.getDefault());
		for (int i = 0; i < avaibleLocales.length; i++) {
			String str = avaibleLocales[i].getDisplayLanguage();
			if (!tmp.equals(str) && !defaultLanguage.equals(str)) {
				localeStringAdapter.add(str);
				localeList.add(avaibleLocales[i]);
				tmp = str;
			}
		}
		localeSpinner.setAdapter(localeStringAdapter);

		// userSpinner population
		userAdapter = new ArrayAdapter<ProfileDAO>(this,
				android.R.layout.simple_spinner_item);
		ArrayList<ProfileDAO> profiles = ProfileLogic.getInstance(dbHelper)
				.getProfilesList();
		for (int i = 0; i < profiles.size(); i++) {
			userAdapter.add(profiles.get(i));
		}
		userSpinner.setAdapter(userAdapter);

		// Buttons listeners
		registerNowButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				showRegisterForm();
			}
		});

		loginNowButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				showLoginForm();
			}
		});

		loginButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				ProfileDAO profile = (ProfileDAO) userSpinner.getSelectedItem();
				String password = passwordEdit.getText().toString();
				if (profile == null || password.equals("")) {
					showDialog(DIALOG_FIELD_ERROR_ID);
					return;
				}

				// Get md5
				password = DataBaseHelper.md5(password);

				// Verify login
				boolean result = ProfileLogic.getInstance(dbHelper).login(
						profile.getID(), password);

				if (!result) {
					showDialog(DIALOG_LOGIN_FAIL_ID);
					return;
				}

				Intent intent = new Intent(LoginActivity.this,
						MenuActivity.class);
				intent.putExtra("profile_id", profile.getID());
				startActivity(intent);
			}
		});

		registerButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String firstName = firstNameEdit.getText().toString();
				String lastName = lastNameEdit.getText().toString();
				String password = passwordRegistrationEdit.getText().toString();
				if (firstName.equals("") || lastName.equals("")
						|| password.equals("")) {
					showDialog(DIALOG_FIELD_ERROR_ID);
					return;
				}

				// Get md5
				password = DataBaseHelper.md5(password);

				// Get all data
				Date registrationDate = new Date();
				Locale locale = localeList.get(localeSpinner
						.getSelectedItemPosition());
				Date birthDate = new Date(birthdayPicker.getYear(),
						birthdayPicker.getMonth(), birthdayPicker
								.getDayOfMonth());

				// Change language configuration according to the user language
				String preferredLanguage;
				String preferredTts = "";
				Resources res = getResources();
				Configuration config = res.getConfiguration();
				config.locale = locale;
				res.updateConfiguration(config, null);

				// Use italian as preferred language if no translation is
				// available
				Locale tmp;
				if (LoginActivity.this.getString(R.string.yes).equals("Si")) {
					tmp = Locale.ITALIAN;
				} else {
					tmp = locale;
				}
				preferredLanguage = tmp.getLanguage();
				// Change tts language configuration according to the user
				// language
				if ((tts.isLanguageAvailable(tmp) == TextToSpeech.LANG_AVAILABLE)
						|| (tts.isLanguageAvailable(tmp) == TextToSpeech.LANG_COUNTRY_AVAILABLE)) {
					preferredTts = tmp.getLanguage();
				}

				// Create ProfileDAO
				ProfileDAO profile = new ProfileDAO(-1, password, firstName,
						lastName, birthDate, locale.getLanguage(), 1,
						registrationDate);
				profile.setPreferredLanguage(preferredLanguage);
				profile.setPreferredTts(preferredTts);

				// Save in DB
				int id = ProfileLogic.getInstance(dbHelper).registerProfile(
						getApplicationContext(), profile);

				// Return to custom locale
				config.locale = Locale.getDefault();
				res.updateConfiguration(config, null);

				if (id > -1) {
					showDialog(DIALOG_REGISTER_SUCCESS_ID);
					showLoginForm();
				} else {
					showDialog(DIALOG_REGISTER_FAIL_ID);
				}
			}
		});

	}

	@Override
	public void onPause() {
		super.onPause();

		resetLoginFields();
		resetRegisterFields();
		showLoginForm();
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();

		/*
		 * Kill application when the root activity is killed.
		 */
		System.runFinalizersOnExit(true);
	}

	/*
	 * Visualize the login form cleaning all the fields.
	 */
	private void showLoginForm() {
		resetLoginFields();
		registerLayout.setVisibility(View.GONE);
		loginLayout.setVisibility(View.VISIBLE);
	}

	/*
	 * Visualize the registration form cleaning all the fields.
	 */
	private void showRegisterForm() {
		resetRegisterFields();
		loginLayout.setVisibility(View.GONE);
		registerLayout.setVisibility(View.VISIBLE);
	}

	/*
	 * Clean all the fields.
	 */
	private void resetLoginFields() {
		ArrayList<ProfileDAO> profiles = ProfileLogic.getInstance(dbHelper)
				.getProfilesList();
		userAdapter.clear();
		for (int i = 0; i < profiles.size(); i++) {
			userAdapter.add(profiles.get(i));
		}
		userAdapter.notifyDataSetChanged();
		passwordEdit.setText("");
	}

	private void resetRegisterFields() {
		firstNameEdit.setText("");
		lastNameEdit.setText("");
		passwordRegistrationEdit.setText("");
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		Dialog dialog;
		AlertDialog.Builder builder;
		builder = new AlertDialog.Builder(this);
		builder.setCancelable(false).setPositiveButton(
				getResources().getString(R.string.ok),
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int id) {
						dialog.cancel();
					}
				});
		switch (id) {
		case DIALOG_FIELD_ERROR_ID:
			builder.setMessage(R.string.dialog_field_error);
			break;
		case DIALOG_REGISTER_SUCCESS_ID:
			builder.setMessage(R.string.dialog_register_success);
			break;
		case DIALOG_REGISTER_FAIL_ID:
			builder.setMessage(R.string.dialog_register_fail);
			break;
		case DIALOG_LOGIN_FAIL_ID:
			builder.setMessage(R.string.dialog_login_fail);
			break;
		default:
			dialog = null;
		}
		dialog = builder.create();
		return dialog;
	}
}
